package com.execjar.utils;


import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;

import java.io.Closeable;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 向业务前置发送请求
 *
 * @author dehuisun
 */
@Slf4j
public class TcpToolUtils {

    /**
     * 读取超时时间
     */
    private static int timeOut = 200;

    /**
     * 读取指定长度的字节
     *
     * @param ip     IP
     * @param port   端口
     * @param length 长度
     * @return 读取到的字节
     */
    public static List<byte[]> postReAssignByteList(String ip, int port, int length, int timeOut) {
        Socket socket = null;
        InputStream is = null;
        // 读取成功
        Boolean netErr = Boolean.TRUE;
        ArrayList<byte[]> list = Lists.newArrayList();
        try {
            socket = new Socket();
            socket.connect(new InetSocketAddress(ip, (port)), timeOut);
            socket.setSoTimeout(timeOut);
            is = socket.getInputStream();

            netErr = Boolean.FALSE;

            byte[] buffer = new byte[length]; // 可以根据需要调整缓冲区大小
            int bytesRead;
            // 循环读取数据直到连接关闭或发生异常
            for (int count = 0; count < 10; count++) {
                bytesRead = is.read(buffer);
                // 处理接收到的数据
                byte[] message = Arrays.copyOf(buffer, bytesRead);
                log.info("读取到的数据[{}]", new String(message, StandardCharsets.UTF_8));
                list.add(message);
            }
        } catch (Exception e) {
            log.error("TCP错误", e);
            if (netErr) {
                throw new SqException(Integer.valueOf(ConstantEnum.EQU_NET_ERR.getCode()), ConstantEnum.EQU_NET_ERR.getName());
            }
            throw new SqException(Integer.valueOf(ConstantEnum.EQU_MSG_ERR.getCode()), ConstantEnum.EQU_MSG_ERR.getName());
        } finally {
            // 关闭连接和I/O,释放资源
            closeAll(is, socket);
        }
        return list;
    }


    /**
     * 读取指定长度的字节
     *
     * @param ip     IP
     * @param port   端口
     * @param length 长度
     * @return 读取到的字节
     */
    public static byte[] postReAssignByte(String ip, int port, int length) throws IOException {
        Socket socket = null;
        InputStream is = null;
        // 读取成功
        Boolean netErr = Boolean.TRUE;
        try {
            socket = new Socket();
            //连接超时网络异常
            socket.connect(new InetSocketAddress(ip, port), timeOut);
            socket.setSoTimeout(timeOut);
            netErr = Boolean.FALSE;
            byte[] message = new byte[length];
            is = socket.getInputStream();
            //读取超时
            is.read(message);// 接收服务器的响应信息
            return message;
        } catch (Exception e) {
            if (netErr) {
                throw e;
            }
            throw e;
        } finally {
            // 关闭连接和I/O,释放资源
            closeAll(is, socket);
        }
    }

    /**
     * 发送并读取指定长度的字节
     *
     * @param ip     ip
     * @param port   端口
     * @param msg    发送的字节
     * @param length 读取的长度
     * @return 读取到的字节
     * @throws IOException
     */
    public static byte[] postReAssignByte(String ip, int port, byte[] msg, int length) throws IOException {
        Socket socket = null;
        InputStream is = null;
        DataOutputStream dos = null;
        Boolean netErr = Boolean.TRUE;
        try {
            socket = new Socket();
            socket.connect(new InetSocketAddress(ip, port), timeOut);
            socket.setSoTimeout(timeOut);
            netErr = Boolean.FALSE;
            if (msg != null) {
                dos = new DataOutputStream(socket.getOutputStream());
                dos.write(msg);
                dos.flush();
            }
            if (length > 0) {
                byte[] message = new byte[length];
                is = socket.getInputStream();
                is.read(message);// 接收服务器的响应信息
                return message;
            }
            return null;

        } catch (Exception e) {
            if (netErr) {
                throw e;
            }
            throw e;
        } finally {
            // 关闭连接和I/O,释放资源
            closeAll(is, dos, socket);
        }
    }

    /**
     * tcpPost
     *
     * @throws IOException 读取指定长度byte的返回数据，防止有过长的空串
     */
    public static String postReAssignByte(String ip, int port, int length, String charSet) throws IOException {
        Socket socket = null;
        InputStream is = null;
        String value = "";
        try {
            socket = new Socket();
            socket.connect(new InetSocketAddress(ip, port), timeOut);
            socket.setSoTimeout(timeOut);
            byte[] message = new byte[length];
            is = socket.getInputStream();
            is.read(message);// 接收服务器的响应信息
            value = new String(message, charSet);
        } catch (SocketTimeoutException e) {
            throw e;
        } catch (Exception e) {
            throw e;
        } finally {
            // 关闭连接和I/O,释放资源
            closeAll(is, socket);
        }
        return value;
    }

    /**
     * tcpPost
     *
     * @throws IOException
     */
    public static String post(String ip, int port, String data) throws IOException {
        Socket socket = null;
        InputStream is = null;
        byte message[] = null;
        DataOutputStream dos = null;
        String value = "";
        try {
            String tradeMessage = data;
            socket = new Socket(ip, port);
            socket.setSoTimeout(timeOut);
            byte[] msg = tradeMessage.getBytes("UTF-8");
            dos = new DataOutputStream(socket.getOutputStream());
            dos.write(msg);
            dos.flush();
            message = new byte[1024];
            is = socket.getInputStream();
            is.read(message);//接收服务器的响应信息
            value = new String(message);
            System.out.println("返回的数据：" + value);
        } catch (SocketTimeoutException e) {
            throw e;
        } catch (Exception e) {
            log.error("tcp连接异常", e);
        } finally {// 关闭连接和I/O,释放资源
            closeAll(is, dos, socket);
        }
        return value;
    }

    /**
     * tcpPost
     *
     * @throws IOException
     */
    public static void postwithoutresponse(String ip, int port, String data) throws IOException {
        Socket socket = null;
        DataOutputStream dos = null;
        try {
            String tradeMessage = data;
            socket = new Socket(ip, port);
            socket.setSoTimeout(timeOut);
            byte[] msg = tradeMessage.getBytes("UTF-8");
            dos = new DataOutputStream(socket.getOutputStream());
            dos.write(msg);
            dos.flush();

        } catch (Exception e) {
            log.error("tcp连接异常", e);
            throw e;
        } finally {// 关闭连接和I/O,释放资源
            closeAll(null, dos, socket);
        }
    }

    /**
     * tcpPost返回字节流
     *
     * @throws IOException
     */
    public static byte[] postReByte(String ip, int port, String data) throws IOException {
        Socket socket = null;
        InputStream is = null;
        byte message[] = null;
        DataOutputStream dos = null;
        try {
            String tradeMessage = data;
            socket = new Socket(ip, port);
            socket.setSoTimeout(timeOut);
            byte[] msg = tradeMessage.getBytes("UTF-8");
            dos = new DataOutputStream(socket.getOutputStream());
            dos.write(msg);
            dos.flush();
            message = new byte[1024];
            is = socket.getInputStream();
            is.read(message);//接收服务器的响应信息
        } catch (Exception e) {
            log.error("tcp连接异常", e);
        } finally {// 关闭连接和I/O,释放资源
            closeAll(is, dos, socket);
        }
        return message;
    }

    /**
     * tcpPost   按照发送字节
     *
     * @throws IOException
     */
    @SuppressWarnings("finally")
    public static String postBytes(String ip, int port, byte[] msg) throws Exception {
        Socket socket = null;
        InputStream is = null;
        byte message[] = null;
        DataOutputStream dos = null;
        String value = "";
        try {
            socket = new Socket(ip, port);
            socket.setSoTimeout(timeOut);
            dos = new DataOutputStream(socket.getOutputStream());
            dos.write(msg);
            dos.flush();
            message = new byte[1024];
            is = socket.getInputStream();
            is.read(message);//接收服务器的响应信息
            value = new String(message);
        } catch (SocketTimeoutException e) {
            throw e;
        } catch (Exception e) {
            log.error("tcp连接异常", e);
            throw e;
        } finally {
            // 关闭连接和I/O,释放资源
            closeAll(is, dos, socket);
            return value;
        }

    }


    /**
     * tcpPost返回指定字节的16进制字符串
     *
     * @throws IOException
     */
    public static String postRe16Self(String ip, int port, byte[] data, int length) throws IOException {
        Socket socket = null;
        InputStream is = null;
        byte message[] = null;
        DataOutputStream dos = null;
        String mes = "";
        try {
            socket = new Socket(ip, port);
            socket.setSoTimeout(timeOut);
            dos = new DataOutputStream(socket.getOutputStream());
            dos.write(data);
            dos.flush();
            message = new byte[length];
            is = socket.getInputStream();
            is.read(message);//接收服务器的响应信息
            mes = HexStrConvers.byte2HexStr(message);
            System.out.println("返回的数据：" + mes);
            //			value = new String(message);
        } catch (SocketTimeoutException e) {
            throw e;
        } catch (Exception e) {
            log.error("tcp连接异常", e);
            throw e;
        } finally {// 关闭连接和I/O,释放资源
            closeAll(is, dos, socket);
        }
        return mes;
    }


    /**
     * tcpPost返回16进制字符串
     *
     * @throws IOException
     */
    public static String postRe16(String ip, int port, String data) throws IOException {
        Socket socket = null;
        InputStream is = null;
        byte message[] = null;
        DataOutputStream dos = null;
        String mes = "";
        try {
            String tradeMessage = data;
            socket = new Socket(ip, port);
            socket.setSoTimeout(timeOut);
            byte[] msg = tradeMessage.getBytes("UTF-8");
            dos = new DataOutputStream(socket.getOutputStream());
            dos.write(msg);
            dos.flush();
            message = new byte[1024];
            is = socket.getInputStream();
            is.read(message);//接收服务器的响应信息
            mes = HexStrConvers.byte2HexStr(message);
            System.out.println("返回的数据：" + mes);
            //			value = new String(message);
        } catch (SocketTimeoutException e) {
            throw e;
        } catch (Exception e) {
            log.error("tcp连接异常", e);
            throw e;
        } finally {// 关闭连接和I/O,释放资源
            closeAll(is, dos, socket);
        }
        return mes;
    }


    /**
     * tcpPost 发送16进制字节数组
     *
     * @throws IOException
     */
    public static boolean postBytesReBoolen(String ip, int port, byte[] msg) throws Exception {
        Socket socket = null;
        DataOutputStream dos = null;
        try {
            socket = new Socket();
            socket.connect(new InetSocketAddress(ip, port), timeOut);//设置连接请求超时时间100 毫秒
            socket.setSoTimeout(timeOut);
            dos = new DataOutputStream(socket.getOutputStream());
            dos.write(msg);
            dos.flush();
            return true;
        } catch (Exception e) {
            log.error("tcp连接异常", e);
            throw e;
        } finally {// 关闭连接和I/O,释放资源
            closeAll(dos, socket);
        }
    }

    public static void closeAll(Closeable... cs) {
        for (Closeable c : cs) {
            if (c != null) {
                try {
                    c.close();
                } catch (IOException e) {
                    //ignore
                }
            }
        }
    }
}
